home *** CD-ROM | disk | FTP | other *** search
- Path: engnews1.Eng.Sun.COM!taumet!clamage
- From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
- Newsgroups: comp.std.c++
- Subject: Re: Array function params and const qualifier
- Date: 12 Apr 1996 15:30:08 GMT
- Organization: Comp Sci, University of Melbourne
- Approved: clamage@eng.sun.com (comp.std.c++)
- Message-ID: <4klir4$63e@mulga.cs.mu.OZ.AU>
- References: <4ke06a$rp3@mozart.wg.icl.co.uk> <4kjqqa$bol@engnews1.Eng.Sun.COM>
- NNTP-Posting-Host: taumet.eng.sun.com
- X-Nntp-Posting-Host: munta.cs.mu.oz.au
- Content-Length: 6778
- X-Lines: 151
- Originator: clamage@taumet
-
- clamage@Eng.Sun.COM (Steve Clamage) writes:
-
- >Adel El-Beik <A.El-Beik@man0506.wins.icl.co.uk> writes:
- >>I have a question concerning MSVC++ v.4.00 and the April DWP C++.
- >>
- >>The following code fails on MSVC++. It doesn't like line labelled 1.
- >>It complains with
- >>
- >>C:\array\array.cpp(16) : error C2664: 'func' : cannot convert parameter 1
- >>from 'long [2][2]' to 'const long [][2]' (new behavior; please see help)
- >
- >You have run into effectively the same rule that prohibits implicit
- >conversion from "T**" to "const T**". That prohibition is not new,
- >but is in the ISO/ANSI C standard, and has not been changed, since
- >it would open a hole in the type system.
-
- I suspect you are mistaken. I believe Adel El-Beik has run into a bug
- in MSVC++, rather than any prohibition in the draft C++ standard.
- By my reading of the January 96 draft, I believe Adel El-Beik's code is
- well-formed (i.e. legal).
-
- [moderator's note: I agree I was wrong. Sorry for the confusion. -sdc ]
-
- >I believe the subject is covered in the comp.lang.c FAQ list.
-
- The comp.lang.c FAQ list may cover the case of conversion from `T**' to
- `const T**' (although I couldn't find it in my old copy), but I'm sure
- it does not cover the case of conversion from `T[n][m]' to `const
- T(*)[m]', which I think is quite safe, and which is, I believe,
- permitted by the draft C++ standard.
-
- Here's the code again, and an explanation of why I believe the code is legal.
-
- typedef long bar[2][2];
- void func( const bar param ){}
-
- int main()
- {
- bar x;
- func(x); // rejected by
- }
-
- The parameter of `func' is declared to have type `const bar', where
- `bar' is a typedef which names an array type. Consulting 3.9.3/3,
-
- | 3.9.3 CV-qualifiers [basic.type.qualifier]
- |
- | 2 A compound type (_basic.compound_) is not cv-qualified by the cv-
- | qualifiers (if any) of the type from which it is compounded. Any cv-
- | qualifiers that appear in an array declaration apply to the array ele-
- | ment type, not the array type (_dcl.array_).
-
- I think we can discern that the declared type of the
- parameter is "array [2] of array [2] of const long", rather than
- "const array [2] of array [2] of long". The wording is quite vague [*]
- but I'm pretty sure that's the intent. However, this is certainly
- the weakest step in my chain of reasoning.
-
- [*] What exactly is an "array declaration"? Does `const bar'
- count as one? Does this rule apply recursively to arrays
- of arrays?
-
- Next, we need to consult 8.3.5/3.
-
- | 8.3.5 Functions [dcl.fct]
- |
- | 3 [...] The type of a function is determined using the follow-
- | ing rules. The type of each parameter is determined from its own
- | decl-specifier-seq and declarator. After determining the type of each
- | parameter, any parameter of type "array of T" or "function returning
- | T" is adjusted to be "pointer to T" or "pointer to function returning
- | T," respectively. [...]
-
- In this case, the type of the parameter is adjusted from "array [2] of
- array [2] of const long" to "pointer to array [2] of const long".
-
- So, we are trying to convert a value of type "array [2] of array [2] of long"
- to type "pointer to array [2] of const long". According to 4/1,
-
- | 4 Standard conversions [conv]
- |
- | 1 Standard conversions are implicit conversions defined for built-in
- | types. The full set of such conversions is enumerated in this clause.
- | A standard conversion sequence is a sequence of standard conversions
- | in the following order:
- |
- | --Zero or one conversion from the following set: lvalue-to-rvalue con-
- | version, array-to-pointer conversion, and function-to-pointer con-
- | version.
- |
- | --Zero or one conversion from the following set: integral promotions,
- | floating point promotion, integral conversions, floating point con-
- | versions, floating-integral conversions, pointer conversions,
- | pointer to member conversions, base class conversions, and boolean
- | conversions.
- |
- | --Zero or one qualification conversion.
-
- The first conversion we apply, then, is an array-to-pointer conversion.
- Consulting 4.2/1,
-
- | 4.2 Array-to-pointer conversion [conv.array]
- |
- | 1 An lvalue or rvalue of type "array of N T" or "array of unknown bound
- | of T" can be converted to an rvalue of type "pointer to T." The
- | result is a pointer to the first element of the array.
-
- we see that we can convert our value of type "array [2] of array[2] of long"
- to "pointer to array [2] of long".
-
- We don't need to apply any conversions from the second set, but we
- do need to apply a qualification conversion before we can get to
- "pointer to array [2] of const long". At first glance, 4.4/1
-
- | 4.4 Qualification conversions [conv.qual]
- |
- | 1 An rvalue of type "pointer to cv1 T" can be converted to an rvalue of
- | type "pointer to cv2 T" if "cv2 T" is more cv-qualified than "cv1 T."
-
- does not seem to be of any help, since the "const" is on the wrong
- side of the "array of". However, this must be read in the context
- of 3.9.3/5.
-
- | 3.9.3 CV-qualifiers [basic.type.qualifier]
- |
- | 5 In this International Standard, the notation cv (or cv1, cv2, etc.),
- | used in the description of types, represents an arbitrary set of cv-
- | qualifiers, i.e., one of {const}, {volatile}, {const, volatile}, or
- | the empty set. Cv-qualifiers applied to an array type attach to the
- | underlying element type, so the notation "cv T," where T is an array
- | type, refers to an array whose elements are so-qualified. Such array
- | types can be said to be more (or less) cv-qualified than other types
- | based on the cv-qualification of the underlying element types.
-
- In our case, T is indeed an array type. Reading 4.4/1 with `cv T'
- everywhere replaced with `array of cv T', as is required by 3.9.3,
- gives us the following rule:
-
- || An rvalue of type "pointer to array of cv1 T" can be converted to an
- || rvalue of type "pointer to array of cv2 T" if "cv2 T" is more
- || cv-qualified than "cv1 T."
-
- Applying this rule to the case in question, we can convert to "pointer
- to array [2] of long" to "pointer to array [2] of const long", since
- "const long" is more cv-qualified than "long". At this point, we
- have shown that there exists a standard conversion sequence which converts
- the type of the actual parameter of `func' to the type of its formal
- parameter, and so it should be clear that the example is well-formed.
-
- --
- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
- WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
- PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
-
-
- [ comp.std.c++ is moderated. To submit articles: try just posting with ]
- [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
- [ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
- [ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
- [ Comments? mailto:std-c++-request@ncar.ucar.edu ]
-